package solver

import (
	"fmt"
	"log"
	"slices"
	"strings"
)

/*
	func intRange(n int) []int {
		xs := make([]int, n)
		for i := 0; i < n; i++ {
			xs[i] = i
		}
		return xs
	}
*/
func fishLines(lines [9]House, cellCount int) (used bool) {
	for _, lineNums := range combine(
		[]int{0, 1, 2, 3, 4, 5, 6, 7, 8}, cellCount) {
		for cand := 0; cand < 9; cand++ {
			cellNums := verifyFishLine(lines, cand, lineNums)
			if len(cellNums) != cellCount {
				continue
			}
			if clearupFishLines(lines, cand, lineNums, cellNums) {
				used = true
				fishLog(lines, cand, lineNums, cellNums)
			}
		}
	}

	return
}
func verifyFishLine(lines [9]House, cand int, lineNums []int) (cellNums []int) {
	candCells := [9]bool{}
	for _, lineNum := range lineNums {
		for j := 0; j < 9; j++ {
			candCells[j] = candCells[j] || lines[lineNum].cells[j].cands[cand]
		}
	}
	cellNums = intsFromBools(candCells)
	return
}

func fishLog(lines [9]House, cand int, lineNums []int, cellNums []int) {
	var b strings.Builder
	var firstHouse, secondHouse string
	if lines[0].HouseType() == 0 { //row
		firstHouse = "r"
		secondHouse = "c"
	} else {
		firstHouse = "c"
		secondHouse = "r"
	}

	fmt.Fprint(&b, firstHouse)
	for _, num := range lineNums {
		fmt.Fprint(&b, num)
	}
	fmt.Fprint(&b, secondHouse)
	for _, num := range cellNums {
		fmt.Fprint(&b, num)
	}
	fmt.Fprintf(&b, " %v ", cand+1)
	switch len(lineNums) {
	case 2:
		fmt.Fprint(&b, "XWing")
	case 3:
		fmt.Fprint(&b, "Swordfish")
	case 4:
		fmt.Fprint(&b, "Jellyfish")
	}

	log.Println(b.String())
}

func clearupFishLines(lines [9]House, cand int, lineNums []int, cellNums []int) (used bool) {
	for lineNum, line := range lines {
		if slices.Contains(lineNums, lineNum) {
			continue
		}
		for _, cellNum := range cellNums {
			cell := line.cells[cellNum]
			if cell.solved() {
				continue
			}
			if cell.removeCand(cand) {
				used = true
			}
		}
	}
	return
}

func (g *Grid) XWing() (used bool) {
	if fishLines(g.rows, 2) {
		used = true
	}
	if fishLines(g.cols, 2) {
		used = true
	}
	return
}

func (g *Grid) Swordfish() (used bool) {
	if fishLines(g.rows, 3) {
		used = true
	}
	if fishLines(g.cols, 3) {
		used = true
	}
	return
}

func (g *Grid) Jellyfish() (used bool) {
	if fishLines(g.rows, 4) {
		used = true
	}
	if fishLines(g.cols, 4) {
		used = true
	}
	return
}
